import os
import shutil
import time

class_dict = {
	'zip':'package', 'gz':'package', 'tgz':'package', '7z':'package', 'rar':'package', 'iso':'package', 'run':'package', 'deb':'package', 'tar':'package',
	'png':'image', 'jpg' : 'image',  'jpeg':'image', 'tif':'image', 'tiff':'image',
	'dav':'video', 'avi':'video', 'mpeg2':'video',
	'cpp':'script', 'hpp':'script', 'h':'script', 'cc':'script', 'py':'script', 'pyc':'script', 'm':'script', 'sh':'script',
	'msi':'win', 'exe':'win', 'dll':'win',
	'pdf':'doc', 'xls':'doc', 'xlsx':'doc', 'csv':'doc', 'ppt':'doc', 'pptx':'doc', 'doc':'doc', 'docx':'doc', 'txt':'doc'
}

def log_msg(msg):
	print(msg)

def reversed_map(map):
	vlist = []
	for k in map.keys():
		v = map[k]
		if v not in vlist:
			vlist.append(v)
	return vlist

def sorted_dict(d):
	for k in d.keys():
		d[k] = sorted(d[k])
	return d


def get_dlist_infolder(root_path):
	dlist = []
	for d in os.listdir(root_path):
		if d == '.' or d == '..':
			continue
		if os.path.isdir(d):
			dlist.append(os.path.join(root_path, d))
	return dlist

def get_flist_infolder(root_path):
	flist = []
	for f in os.listdir(root_path):
		fpath = os.path.join(root_path, f)
		if os.path.isfile(fpath):
			flist.append(fpath)
	return flist

def mkdirs_ifneeded(root_path, folder_list):
	for d in folder_list:
		subdir = os.path.join(root_path, d)
		if not os.path.exists(subdir):
			log_msg('making new folder %s' % subdir)
			os.mkdir(subdir)

def mkfile_ifneeded(root_path, f):
	f_path = os.path.join(root_path, f)
	if not os.path.exists(f_path):
		log_msg('making new file %s' % f_path)
		with open(f, 'w') as h:
			pass
		return True
	else:
		return False

def load_repo_dict(root_path, repo_f):
	repo_path = os.path.join(root_path, repo_f)
	is_new_log = mkfile_ifneeded(root_path, repo_f)
	repo_dict = {}
	if not is_new_log:
		with open(repo_path, 'r') as h: # load repo_dict
			for line in h.readlines():
				k, v = line.rstrip('\t\r\n').split('\t')
				fpath = os.path.join(root_path, '%s/%s' % (k, v))
				if k not in repo_dict.keys():
					repo_dict[k] = [fpath]
				else:
					repo_dict[k].append(fpath)
	return sorted_dict(repo_dict)

def write_repo_dict(root_path, repo_f, repo_dict):
	if len(repo_dict.keys()) < 1:
		log_msg('empty repository')
		return
	repo_path = os.path.join(root_path, repo_f)
	with open(repo_f, 'w') as h:
		for k in repo_dict:
			[h.write('%s\t%s\n' % (k, v.split('/')[-1])) for v in repo_dict[k]]

def updated_repo_dict(root_path):
	new_repo_dict = {}
	for subdir in reversed_map(class_dict):
		sub_path = os.path.join(root_path, subdir)
		if not os.path.exists(sub_path):
			continue
		for f in get_flist_infolder(sub_path):
			if subdir not in new_repo_dict.keys():
				new_repo_dict[subdir] = [f]
			elif f not in new_repo_dict[subdir]:
				new_repo_dict[subdir].append(f)
	return sorted_dict(new_repo_dict)

def move_ifneeded(src, dst):
	dst_f = None
	if os.path.isdir(dst):
		f = src.split('/')[-1]
		dst_f = os.path.join(dst, f)
	else:
		dst_f = dst
	old_dst_f = dst_f + ' (1)'
	cp_idx = 1
	while(1):
		if os.path.exists(old_dst_f):
			cp_idx += 1
			old_dst_f = dst_f + ' (%d)' % cp_idx
		else:
			if os.path.exists(dst_f):
				shutil.move(dst_f, old_dst_f)
			break
	shutil.move(src, dst)

def archive_file(root_path, f):
	postfix = f.split('.')[-1]
	has_new_file = False
	for pattern in class_dict.keys():
		if postfix == pattern:
			src = os.path.join(root_path, f)
			dst = os.path.join(root_path, class_dict[pattern])
			log_msg('archive downloaded file %s to %s' % (f, dst))
			mkdirs_ifneeded(root_path, [dst])
			move_ifneeded(src, dst)
			has_new_file = True
	return has_new_file

if __name__=='__main__':
	root_path = '/home/youngway/downloads'
	repo_f = 'downloads.repolog'
	repo_dict = load_repo_dict(root_path, repo_f)
	repo_dict = updated_repo_dict(root_path)
	write_repo_dict(root_path, repo_f, repo_dict)
	while(1):
		new_file_num = 0
		flist = get_flist_infolder(root_path)
		for f in flist:
			has_new_file = archive_file(root_path, f)
			if has_new_file:
				new_file_num += 1
		#if new_file_num > 0:
		repo_dict = updated_repo_dict(root_path)
		write_repo_dict(root_path, repo_f, repo_dict)
		time.sleep(10)